package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.config.exception.MyRuntimeException;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.entity.pf.AppraisalIndex;
import com.plian.system.entity.pf.BasePerformanceEffect;
import com.plian.system.entity.pf.PerformanceEffectDetail;
import com.plian.system.entity.pf.PerformanceScoreMethod;
import com.plian.system.entity.sys.Office;
import com.plian.system.enumeratea.BusinessIndicatorsStatus;
import com.plian.system.mapper.pf.BasePerformanceEffectMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.node.ForestNodeMerger;
import com.plian.system.properties.GzwProperties;
import com.plian.system.service.pf.IAppraisalIndexService;
import com.plian.system.service.pf.IPerformanceEffectDetailService;
import com.plian.system.service.pf.IPerformanceScoreMethodService;
import com.plian.system.service.pf.IPerformanceScoreService;
import com.plian.system.service.sys.office.IOfficeService;
import com.plian.system.vo.pf.AppraisalIndexVO;
import com.plian.system.vo.pf.BasePerformanceEffectVO;
import com.plian.system.vo.pf.ScoreMethodVO;
import com.plian.system.wrapper.pf.AppraisalIndexWrapper;
import com.plian.system.wrapper.pf.BasePerformanceEffectWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * @Author: Take-off
 * @Description: TODO
 * @Date: 2023/1/17 9:49 AM
 * @Version: 1.0
 **/
@Service
@AllArgsConstructor
public class PerformanceScoreServiceImpl extends BaseServiceImpl<BasePerformanceEffectMapper, BasePerformanceEffect> implements IPerformanceScoreService, BaseFlowService {

    private IPerformanceScoreMethodService performanceScoreMethodService;

    private IPerformanceEffectDetailService effectDetailService;

    private BasePerformanceEffectWrapper basePerformanceEffectWrapper;

    private IAppraisalIndexService appraisalIndexService;

    private AppraisalIndexWrapper appraisalIndexWrapper;

    private GzwProperties gzwProperties;

    private IOfficeService officeService;

    @Override
    public boolean saveOrUpdate(BasePerformanceEffect basePerformanceEffect) {
        if (!Optional.ofNullable(basePerformanceEffect.getStatus()).isPresent()) {
            basePerformanceEffect.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (basePerformanceEffect.getStatus().equals(FormStatusConstant.REJECT)) {
            basePerformanceEffect.setStatus(FormStatusConstant.UNREVIEWED);
        }

        if (!Optional.ofNullable(basePerformanceEffect.getId()).isPresent()) {
            basePerformanceEffect.setFormType(String.valueOf(FormTypeConstant.PF_PERFORMANCE_SCORE));
            basePerformanceEffect.setVersion(1);
            basePerformanceEffect.setIsLatest(2);
        }
        return super.saveOrUpdate(basePerformanceEffect);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BasePerformanceEffect basePerformanceEffect = getById(id);
            if (basePerformanceEffect == null) {
                return false;
            }
        }
        boolean result = super.deleteLogic(ids);
        if (result){
            performanceScoreMethodService.deleteByParentId(ids);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(BasePerformanceEffect basePerformanceEffect) {
        boolean result = saveOrUpdate(basePerformanceEffect);
        if (result){
            List<PerformanceScoreMethod> performanceScoreMethods = basePerformanceEffect.getPerformanceScoreMethods();
            if (CollectionUtil.isNotEmpty(performanceScoreMethods)){
                for (PerformanceScoreMethod scoreMethod : performanceScoreMethods){
                    if (scoreMethod.getId() != null &&
                            Optional.ofNullable(scoreMethod.getIsDeleted()).isPresent() && scoreMethod.getIsDeleted().intValue() == 1) {
                        performanceScoreMethodService.removeById(scoreMethod.getId());
                    }else {
                        scoreMethod.setBasePerformanceId(basePerformanceEffect.getId());
                        performanceScoreMethodService.saveOrUpdate(scoreMethod);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public BasePerformanceEffectVO getDetailObj(BasePerformanceEffect basePerformanceEffect) {
        BasePerformanceEffectVO basePerformanceEffectVO = new BasePerformanceEffectVO();

        Long id = basePerformanceEffect.getId();
        if (Optional.ofNullable(id).isPresent()) {
            basePerformanceEffectVO = basePerformanceEffectWrapper.entityToVO(getById(id));
        }
        //评分办法
        List<PerformanceScoreMethod> detailList = performanceScoreMethodService.list(new LambdaQueryWrapper<PerformanceScoreMethod>().eq(PerformanceScoreMethod::getBasePerformanceId, id)
                .orderByAsc(PerformanceScoreMethod::getIndexNum));
        //set officeName
        if (CollectionUtil.isNotEmpty(detailList)){
            List<Office> offices = officeService.list(new LambdaQueryWrapper<Office>().in(Office::getId,
                    detailList.stream().map(PerformanceScoreMethod::getReportOffice).collect(Collectors.toList())));
            detailList.forEach(detail ->{
                List<Office> officeList = offices.stream().filter(m -> detail.getReportOffice().equals(m.getId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(officeList)){
                    detail.setReportOfficeName(officeList.get(0).getName());
                }
            });
            basePerformanceEffectVO.setPerformanceScoreMethods(detailList);
        }

        return basePerformanceEffectVO;
    }


    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        BasePerformanceEffect performanceEffect = getById(id);
        performanceEffect.setApprovedUser(TokenUtil.getTokenUserId());
        Date now = DateUtil.now();
        performanceEffect.setApprovedTime(now);
        performanceEffect.setIsLatest(2);
        performanceEffect.setVersion(1);
        performanceEffect.setInitialId(Long.valueOf(id));
        performanceEffect.setIndicatorStatus(BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
        updateById(performanceEffect);

        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
    }

    @Override
    public Boolean reject(String id, int formState,String comment) {
        return handleStatus(Long.valueOf(id), formState);
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BasePerformanceEffect> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BasePerformanceEffect::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BasePerformanceEffect> performanceEffects = list(queryWrapper);
        List<BasePerformanceEffectVO> performanceEffectVOS = basePerformanceEffectWrapper.entityToVO(performanceEffects);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(performanceEffectVOS)){
                for (BasePerformanceEffectVO vo : performanceEffectVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getReportOfficeName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getReportOffice());
                    pd.put("formType", FormTypeConstant.PF_PERFORMANCE_SCORE);
                    pd.put("orgName", vo.getReportOfficeName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.PF_PERFORMANCE_SCORE);
    }

    @Override
    public void goBackToStash(String formId) {
        Long id = Long.valueOf(formId);
        List<BasePerformanceEffect> performanceEffects = list(new LambdaQueryWrapper<BasePerformanceEffect>().eq(BasePerformanceEffect::getInitialId, id));
        if (CollectionUtil.isNotEmpty(performanceEffects) && performanceEffects.size() > 1){
            throw new MyRuntimeException(new ObjResult("该单据已进行其他操作，无法退回！"));
        }
        BasePerformanceEffect performanceEffect = getById(id);
        if (performanceEffect.getStatus() == FormStatusConstant.FINISH){
            LambdaUpdateWrapper<BasePerformanceEffect> updateWrapper = new LambdaUpdateWrapper<>();
            update(updateWrapper.eq(BasePerformanceEffect::getId, id)
                    .set(BasePerformanceEffect::getApprovedUser, null).set(BasePerformanceEffect::getApprovedTime, null)
                    .set(BasePerformanceEffect::getIndicatorStatus, null));
        }
        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            BasePerformanceEffect tripleMeeting = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                tripleMeeting.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                tripleMeeting.setApprovedTime(now);
            }
            tripleMeeting.setStatus(updateStatus);
            updateById(tripleMeeting);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public List<ScoreMethodVO> getAllScoreMethod(String year){
        List<ScoreMethodVO> merge  = new ArrayList<>();
       //todo 只取后三层
        List<AppraisalIndex> allList = getLastThreeIndex();
        //获取考核处汇总的最新的数据
        List<BasePerformanceEffect> effects = list(new LambdaQueryWrapper<BasePerformanceEffect>().eq(BasePerformanceEffect::getReportOffice, gzwProperties.getAssessmentId())
                .eq(BasePerformanceEffect::getFillingYear, year).eq(BasePerformanceEffect::getStatus, 3).eq(BasePerformanceEffect::getIsLatest,2));
        if (CollectionUtil.isNotEmpty(effects)){
            BasePerformanceEffect basePerformanceEffect = effects.get(0);
            //具体评价内容
            List<PerformanceScoreMethod> scoreMethods = performanceScoreMethodService.list(new LambdaQueryWrapper<PerformanceScoreMethod>().eq(PerformanceScoreMethod::getBasePerformanceId, basePerformanceEffect.getId()));
            if (CollectionUtil.isNotEmpty(scoreMethods)){
                List<ScoreMethodVO> scoreMethodVOS = new ArrayList<>();
                allList.forEach(index ->{
                    ScoreMethodVO scoreMethodVO = new ScoreMethodVO();
                    scoreMethodVO.setId(index.getId());
                    scoreMethodVO.setParentId(index.getParentId());
                    scoreMethodVO.setName(index.getName());
                    List<PerformanceScoreMethod> methods = scoreMethods.stream().filter(m -> Optional.ofNullable(m.getBaseBusinessIndicatorsId()).isPresent() && m.getBaseBusinessIndicatorsId().equals(index.getId())).collect(Collectors.toList());
                    scoreMethodVO.setScoreMethodList(methods);
                    scoreMethodVOS.add(scoreMethodVO);
                });
                merge = ForestNodeMerger.merge(scoreMethodVOS);
            }
        }
        return merge;
    }

    @Override
    public   List<AppraisalIndex> getLastThreeIndex(){
        List<AppraisalIndex> appraisalIndices = appraisalIndexService.list(new LambdaQueryWrapper<AppraisalIndex>().eq(AppraisalIndex::getTableCode,"003").orderByAsc(AppraisalIndex::getTableCode,AppraisalIndex::getSort));
        List<AppraisalIndexVO> appraisalIndexVOS = appraisalIndexWrapper.entityToVO(appraisalIndices);
        int maxLevel = 1;
        for (AppraisalIndexVO vo:appraisalIndexVOS){
            Integer level = setCode(vo, appraisalIndexVOS);
            if (level>maxLevel){
                maxLevel = level;
            }
        }
        if (maxLevel >3){
            int level = maxLevel - 3;
            List<AppraisalIndexVO> appraisalIndexVOList = appraisalIndexVOS.stream().filter(m -> m.getLevel() > level).collect(Collectors.toList());
            appraisalIndices = appraisalIndexWrapper.voToEntity(appraisalIndexVOList);
        }
        return appraisalIndices;
    }

    private Integer setCode(AppraisalIndexVO vo,List<AppraisalIndexVO> appraisalIndexVOS){
        int level = 0;
        if (vo.getParentId() == null || vo.getParentId() == 0L){
            vo.setLevel(1);
            return 1;
        }
        Optional<AppraisalIndexVO> optional = appraisalIndexVOS.stream().filter(m -> m.getId().equals(vo.getParentId())).findFirst();
        if (optional.isPresent()){
            AppraisalIndexVO parentIndex = optional.get();
            Integer parentLevel = parentIndex.getLevel();
            if (Optional.ofNullable(parentLevel).isPresent()){
                 level = parentLevel + 1;
                vo.setLevel(level);
                return level;
            }else {
                parentLevel = setCode(parentIndex, appraisalIndexVOS);
                 level = parentLevel + 1;
                vo.setLevel(level);
                return level;
            }
        }
        return level;
    }

    @Override
    public List<ScoreMethodVO> getScoreMethodByOffice(String year,Long officeId){
        List<ScoreMethodVO> scoreMethodVOS = new ArrayList<>();
        List<AppraisalIndex> allList = appraisalIndexService.list(new LambdaQueryWrapper<AppraisalIndex>().eq(AppraisalIndex::getTableCode,"003").orderByAsc(AppraisalIndex::getTableCode,AppraisalIndex::getSort));

        //获取考核处汇总的最新的数据
        List<BasePerformanceEffect> effects = list(new LambdaQueryWrapper<BasePerformanceEffect>().eq(BasePerformanceEffect::getReportOffice, gzwProperties.getAssessmentId())
                .eq(BasePerformanceEffect::getFillingYear, year).eq(BasePerformanceEffect::getStatus, 3).eq(BasePerformanceEffect::getIsLatest,2));
        if (CollectionUtil.isNotEmpty(effects)){
            BasePerformanceEffect basePerformanceEffect = effects.get(0);
            //具体评价内容
            List<PerformanceScoreMethod> scoreMethods = performanceScoreMethodService.list(new LambdaQueryWrapper<PerformanceScoreMethod>()
                    .eq(PerformanceScoreMethod::getBasePerformanceId, basePerformanceEffect.getId()).eq(PerformanceScoreMethod::getReportOffice,officeId));
            if (CollectionUtil.isNotEmpty(scoreMethods)){
                allList.forEach(index ->{
                    ScoreMethodVO scoreMethodVO = new ScoreMethodVO();
                    scoreMethodVO.setId(index.getId());
                    scoreMethodVO.setParentId(index.getParentId());
                    scoreMethodVO.setName(index.getName());
                    List<PerformanceScoreMethod> methods = scoreMethods.stream().filter(m -> Optional.ofNullable(m.getBaseBusinessIndicatorsId()).isPresent() && m.getBaseBusinessIndicatorsId().equals(index.getId())).collect(Collectors.toList());
                    scoreMethodVO.setScoreMethodList(methods);
                    scoreMethodVOS.add(scoreMethodVO);
                });
            }
        }
        return scoreMethodVOS;
    }

    @Override
    public Set<Long> getAllScoreOffice(String year){
        Set<Long> officeIds  = new HashSet<>();
        //获取考核处汇总的最新的数据
        List<BasePerformanceEffect> effects = list(new LambdaQueryWrapper<BasePerformanceEffect>().eq(BasePerformanceEffect::getReportOffice, gzwProperties.getAssessmentId())
                .eq(BasePerformanceEffect::getFillingYear, year).eq(BasePerformanceEffect::getStatus, 3).eq(BasePerformanceEffect::getIsLatest,2));
        if (CollectionUtil.isNotEmpty(effects)){
            BasePerformanceEffect basePerformanceEffect = effects.get(0);
            //具体评价内容
            List<PerformanceScoreMethod> scoreMethods = performanceScoreMethodService.list(new LambdaQueryWrapper<PerformanceScoreMethod>().eq(PerformanceScoreMethod::getBasePerformanceId, basePerformanceEffect.getId()));
            if (CollectionUtil.isNotEmpty(scoreMethods)){
                officeIds = scoreMethods.stream().map(PerformanceScoreMethod::getReportOffice).collect(Collectors.toSet());
            }
        }
        return officeIds;
    }

    @Override
    public String checkYear(BasePerformanceEffect basePerformanceEffect) {
        QueryWrapper<BasePerformanceEffect> queryWrapper = new QueryWrapper<>();
        if (!Optional.ofNullable(basePerformanceEffect.getFillingYear()).isPresent()) {
            return "填报时间为空";
        }
        if (!Optional.ofNullable(basePerformanceEffect.getReportOffice()).isPresent()){
            return "填报单位为空";
        }
        queryWrapper.eq("report_office",basePerformanceEffect.getReportOffice());
        queryWrapper.eq("filling_year", basePerformanceEffect.getFillingYear());
        queryWrapper.eq("form_type", FormTypeConstant.PF_PERFORMANCE_SCORE);
        List<BasePerformanceEffect> list = list(queryWrapper);

        if (CollectionUtil.isEmpty(list)){
            return null;
        }
        return "该年度已填报";
    }

    @Override
    public ListResult<BasePerformanceEffectVO> versionList(Query query) {
        List<SearchEntity> entityList = query.getSearch();
        if (query.getAscs()==null&&query.getDescs()==null){
            query.setDescs("version");
        }
        QueryWrapper<BasePerformanceEffect> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new BasePerformanceEffect()), entityList
        );

        IPage<BasePerformanceEffect> pages = page(Condition.getPage(query), queryWrapper);
        List<BasePerformanceEffectVO> basePerformanceEffectVOS = basePerformanceEffectWrapper.entityToVO(pages.getRecords());
        if (CollectionUtil.isNotEmpty(basePerformanceEffectVOS)){
            List<Long> ids = basePerformanceEffectVOS.stream().map(BasePerformanceEffectVO::getId).collect(Collectors.toList());

            //评分办法
            List<PerformanceScoreMethod> detailList = performanceScoreMethodService.getByParentIds(ids);

            //履职成效考评内容
            List<PerformanceEffectDetail> effectDetails = effectDetailService.list(new LambdaQueryWrapper<PerformanceEffectDetail>().in(PerformanceEffectDetail::getBasePerformanceId, ids));

            basePerformanceEffectVOS.forEach(basePerformanceEffectVO ->{
                List<PerformanceScoreMethod> scoreMethods = detailList.stream().filter(m -> m.getBasePerformanceId().equals(basePerformanceEffectVO.getId())).collect(Collectors.toList());
                basePerformanceEffectVO.setPerformanceScoreMethods(scoreMethods);

                List<PerformanceEffectDetail> effectDetailList = effectDetails.stream().filter(m -> m.getBasePerformanceId().equals(basePerformanceEffectVO.getId())).collect(Collectors.toList());
                basePerformanceEffectVO.setPerformanceEffectDetails(effectDetailList);
            });
        }
        ListResult<BasePerformanceEffectVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(basePerformanceEffectVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }
}
